package com.ruoyi.zhgd.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.StringUtils;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.system.mapper.SysDeptMapper;
import com.ruoyi.zhgd.domain.*;
import com.ruoyi.zhgd.domain.bo.ZjNWarningUserMessageBo;
import com.ruoyi.zhgd.domain.vo.*;
import com.ruoyi.zhgd.mapper.*;
import com.ruoyi.zhgd.service.IZjNWarningUsingService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.ruoyi.zhgd.domain.bo.ZjNLaboratoryTensionRequiresBo;
import com.ruoyi.zhgd.service.IZjNLaboratoryTensionRequiresService;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 张拉技术要求参数Service业务层处理
 *
 * @author tll
 * @date 2023-11-02
 */
@RequiredArgsConstructor
@Service
@DS("sjcj")
public class ZjNLaboratoryTensionRequiresServiceImpl implements IZjNLaboratoryTensionRequiresService {

    private final ZjNLaboratoryTensionRequiresMapper baseMapper;

    private final TensionResultMapper tensionResultMapper;

    private final TensionRecordingMapper tensionRecordingMapper;

    private final IZjNWarningUsingService iZjNWarningUsingService;

    private final ZjNWarningUserMessageMapper zjNWarningUserMessageMapper;

    private final ZjNWarningZlyjMapper zjNWarningZlyjMapper;

    private final ZjNWarningUsingMapper zjNWarningUsingMapper;

    private final SysDeptMapper sysDeptMapper;



    /**
     * 查询张拉技术要求参数
     */
    @Override
    public ZjNLaboratoryTensionRequiresVo queryById(String id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询张拉技术要求参数列表
     */
    @Override
    public TableDataInfo<ZjNLaboratoryTensionRequiresVo> queryPageList(ZjNLaboratoryTensionRequiresBo bo, PageQuery pageQuery) {
        Long deptId = LoginHelper.getDeptId();
        List<SysDept> collect = iZjNWarningUsingService.getDeptTreeTop(deptId);
        List<Long> deptIds = collect.stream().map(SysDept::getDeptId).collect(Collectors.toList());
        bo.setDeptIds(deptIds);
        Page<ZjNLaboratoryTensionRequiresVo> result = baseMapper.page(pageQuery.build(), bo);
        return TableDataInfo.build(result);
    }

    /**
     * 查询张拉技术要求参数列表
     */
    @Override
    public List<ZjNLaboratoryTensionRequiresVo> queryList(ZjNLaboratoryTensionRequiresBo bo) {
        LambdaQueryWrapper<ZjNLaboratoryTensionRequires> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<ZjNLaboratoryTensionRequires> buildQueryWrapper(ZjNLaboratoryTensionRequiresBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<ZjNLaboratoryTensionRequires> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getBaseCode()), ZjNLaboratoryTensionRequires::getBaseCode, bo.getBaseCode());
        lqw.like(StringUtils.isNotBlank(bo.getName()), ZjNLaboratoryTensionRequires::getName, bo.getName());
        lqw.eq(StringUtils.isNotBlank(bo.getInsertBy()), ZjNLaboratoryTensionRequires::getInsertBy, bo.getInsertBy());
        lqw.eq(bo.getInsertTime() != null, ZjNLaboratoryTensionRequires::getInsertTime, bo.getInsertTime());
        lqw.eq(StringUtils.isNotBlank(bo.getDeptId()), ZjNLaboratoryTensionRequires::getDeptId, bo.getDeptId());
        lqw.eq(StringUtils.isNotBlank(bo.getDeptPkid()), ZjNLaboratoryTensionRequires::getDeptPkid, bo.getDeptPkid());
        lqw.eq(bo.getConcreteRatio() != null, ZjNLaboratoryTensionRequires::getConcreteRatio, bo.getConcreteRatio());
        lqw.eq(bo.getExtensionDeviRatio() != null, ZjNLaboratoryTensionRequires::getExtensionDeviRatio, bo.getExtensionDeviRatio());
        lqw.eq(bo.getShrinkageAmountMaxVal() != null, ZjNLaboratoryTensionRequires::getShrinkageAmountMaxVal, bo.getShrinkageAmountMaxVal());
        lqw.eq(bo.getShrinkageAmountMinVal() != null, ZjNLaboratoryTensionRequires::getShrinkageAmountMinVal, bo.getShrinkageAmountMinVal());
        lqw.eq(bo.getTensionDeviVal() != null, ZjNLaboratoryTensionRequires::getTensionDeviVal, bo.getTensionDeviVal());
        return lqw;
    }

    /**
     * 新增张拉技术要求参数
     */
    @Override
    public Boolean insertByBo(ZjNLaboratoryTensionRequiresBo bo) {
        ZjNLaboratoryTensionRequires add = BeanUtil.toBean(bo, ZjNLaboratoryTensionRequires.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改张拉技术要求参数
     */
    @Override
    public Boolean updateByBo(ZjNLaboratoryTensionRequiresBo bo) {
        ZjNLaboratoryTensionRequires update = BeanUtil.toBean(bo, ZjNLaboratoryTensionRequires.class);
        validEntityBeforeSave(update);
        update.setUpdateBy(LoginHelper.getLoginUser().getUsername());
        update.setUpdateTime(new Date());
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(ZjNLaboratoryTensionRequires entity){
        //TODO 做一些数据校验,如唯一约束
        if (ObjectUtils.isEmpty(entity.getDelFlag())) {
            entity.setDelFlag("0");
        }
        if (ObjectUtils.isEmpty(entity.getInsertBy()) && ObjectUtils.isEmpty(entity.getUpdateBy())) {
            entity.setInsertBy(LoginHelper.getLoginUser().getUsername());
            entity.setUpdateBy(LoginHelper.getLoginUser().getUsername());
        }
        if (ObjectUtils.isEmpty(entity.getInsertTime()) && ObjectUtils.isEmpty(entity.getUpdateTime())) {
            entity.setInsertTime(new Date());
            entity.setUpdateTime(new Date());
        }
    }

    /**
     * 批量删除张拉技术要求参数
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    private String status = null;
    private String msgStatus = null;

    // 判定是否合格
    private String tqdStatus = null;
    private String hslStatus = null;

    private BigDecimal concreteRatio = BigDecimal.valueOf(0); // 砼强度（MPA）需达到 砼设计值（MPA）的比例值
    private BigDecimal extensionDeviRatio = BigDecimal.valueOf(0); // 实际伸长值 与 理论伸长值 的偏差比例
    private BigDecimal extensionDeviRatioRes = BigDecimal.valueOf(0);
    private BigDecimal shrinkageAmountMaxVal = BigDecimal.valueOf(0); // 回缩量上限
    private double shrinkageAmountMaxValRes = 0;
    private BigDecimal shrinkageAmountMinVal = BigDecimal.valueOf(0); // 回缩量下限
    private double shrinkageAmountMinValRes = 0;
    private BigDecimal tensionDeviVal = BigDecimal.valueOf(0); // 同一孔号两台张拉仪的张拉力值的偏差比例
    private BigDecimal tensionDeviValRes = BigDecimal.valueOf(0);

    private List<Object> unqualifiedParams = new ArrayList<>(); // 不合格参数
    private final String TEXT1 = " ";
    private final String TEXT2 = ",";
    private final String TEXT3 = "~";

    @Override
    @Transactional
    public void isQualified(String linkCode) {
        if (ObjectUtils.isEmpty(linkCode)) {
            throw new ServiceException("linkCode不能为空");
        }
        // 根据linkCode获取要判定的业务数据
        List<TensionRecordingResVo> vos = tensionRecordingMapper.selectByLinkCode(linkCode);
        // 三标和四标的张拉数据判定是否同一个孔号 需要去掉后缀数字后再判定 例如 N5_A1 N5_A2 视为同一孔号
        vos = handleHoleNumber(vos);
        if (CollectionUtils.isNotEmpty(vos)) {
            String deptId = ObjectUtils.isNotEmpty(vos.get(0).getDeptId()) ? vos.get(0).getDeptId() : null;
            if (ObjectUtils.isEmpty(deptId)) {
                return;
//                throw new ServiceException("没有部门信息，无法校验！");
            }
            TensionRecordingResVo recordingResVo = vos.get(0);
            // 如果当前张拉数据的梁号带有"预张拉",则不作判定,状态置为合格
            String beamNo = recordingResVo.getBeamNo();
            if (ObjectUtils.isNotEmpty(beamNo) && beamNo.contains("预张拉")) {
                TensionRecording item = new TensionRecording();
                item.setId(recordingResVo.getId());
                item.setStatus("1");
                tensionRecordingMapper.statusUpdate(item);
                return;
            }
            // 根据deptId获取祖级列表
            SysDept dept = sysDeptMapper.getById(Long.valueOf(deptId));
            String ancestors = ObjectUtils.isNotEmpty(dept) ? dept.getAncestors() : null;
            String[] ids = ObjectUtils.isNotEmpty(ancestors) ? ancestors.split(",") : new String[]{} ;
            // 获取最新技术要求
            ZjNLaboratoryTensionRequires requirement = baseMapper.getByDeptId(deptId, ids);
            if (ObjectUtils.isNotEmpty(requirement)) {
                List<TensionRecording> recUpdateList = new ArrayList<>();
                setRequirementData(requirement);
                recUpdateList = estimateData(vos, recUpdateList);
                // 更新record表
                if (CollectionUtils.isNotEmpty(recUpdateList) && recUpdateList.size() > 0) {
                    tensionRecordingMapper.updateBatchById(recUpdateList);
                }
                // 推送消息并保存
                if (CollectionUtils.isNotEmpty(recUpdateList) && recUpdateList.size() > 0 && ObjectUtils.isNotEmpty(recordingResVo)) {
                    sendMsg(deptId, recordingResVo, 1);
                }
            }
        }

    }

    /**
     * 张拉手动校验是否合格并更新数据
     */
    @Override
    @Transactional
    public void isQualifiedList(TensionRecordingVo params) {
        if (ObjectUtils.isEmpty(params.getDeptIdList())) {
            throw new ServiceException("部门id不能为空");
        }

        List<TensionRecording> recUpdateList = new ArrayList<>();
        for (String deptId : params.getDeptIdList()) {
            // 根据deptId获取祖级列表
            SysDept dept = sysDeptMapper.getById(Long.valueOf(deptId));
            String ancestors = ObjectUtils.isNotEmpty(dept) ? dept.getAncestors() : null;
            String[] ids = ObjectUtils.isNotEmpty(ancestors) ? ancestors.split(",") : new String[]{} ;
            // 获取最新技术要求
            ZjNLaboratoryTensionRequires requirement = baseMapper.getByDeptId(deptId, ids);
            if (ObjectUtils.isEmpty(requirement)) {
                continue;
            }
            // 获取要判定的张拉列表
            List<TensionRecordingResVo> vos = tensionRecordingMapper.check(deptId);
            TensionRecordingResVo recordingResVo = ObjectUtils.isNotEmpty(vos.get(0)) ? vos.get(0) : new TensionRecordingResVo();
            setRequirementData(requirement);
            recUpdateList = estimateData(vos, recUpdateList);
            // 推送消息并保存
            if (CollectionUtils.isNotEmpty(recUpdateList) && recUpdateList.size() > 0 && ObjectUtils.isNotEmpty(recordingResVo)) {
                sendMsg(deptId, recordingResVo, 0);
            }
        }
        // 更新record表
        if (CollectionUtils.isNotEmpty(recUpdateList) && recUpdateList.size() > 0) {
            recUpdateList.forEach(item -> {
                if (ObjectUtils.isNotEmpty(item)) {
                    tensionRecordingMapper.statusUpdate(item);
                }
            });
        }
    }

    /**
     * 手动校验(多选)
     *
     * @param bo
     */
    @Override
    @Transactional
    public void handCheck(ZjNLaboratoryTensionRequiresBo bo) {
        if (ObjectUtils.isEmpty(bo.getIds())) {
            throw new ServiceException("ID列表不能为空");
        }
        // 根据id查询linkCode
        List<String> ids = bo.getIds();
        List<TensionRecordingResVo> vos = tensionRecordingMapper.getListByIds(ids);
        // 获取linkCode
        List<String> linkCodes = vos.stream().map(TensionRecordingResVo::getLinkCode).collect(Collectors.toList());
        for (String linkCode : linkCodes) {
            // 调用判断方法
            isQualified(linkCode);
        }
    }

    public List<TensionRecordingResVo> handleHoleNumber(List<TensionRecordingResVo> vos) {
        for (TensionRecordingResVo vo : vos) {
            if (ObjectUtils.isNotEmpty(vo.getHoleNumber()) && vo.getHoleNumber().length() > 4 && vo.getHoleNumber().contains("_")) {
                String s = vo.getHoleNumber().substring(0, 4);
                vo.setHoleNumber(s);
            }
        }
        return vos;
    }

    public void setRequirementData(ZjNLaboratoryTensionRequires requirement){
        // 技术要求数据格式转换
        concreteRatio = requirement.getConcreteRatio(); // 砼强度（MPA）需达到 砼设计值（MPA）的比例值
        extensionDeviRatio = requirement.getExtensionDeviRatio(); // 实际伸长值 与 理论伸长值 的偏差比例
        if (ObjectUtils.isNotEmpty(extensionDeviRatio)) {
            extensionDeviRatioRes = extensionDeviRatio.divide(BigDecimal.valueOf(100), 3, BigDecimal.ROUND_HALF_UP);
        }
        shrinkageAmountMaxVal = requirement.getShrinkageAmountMaxVal(); // 回缩量上限
        if (ObjectUtils.isNotEmpty(shrinkageAmountMaxVal)) {
            shrinkageAmountMaxValRes = shrinkageAmountMaxVal.doubleValue();
        }
        shrinkageAmountMinVal = requirement.getShrinkageAmountMinVal(); // 回缩量下限
        if (ObjectUtils.isNotEmpty(shrinkageAmountMinVal)) {
            shrinkageAmountMinValRes = shrinkageAmountMinVal.doubleValue();
        }
        tensionDeviVal = requirement.getTensionDeviVal(); // 同一孔号两台张拉仪的张拉力值的偏差比例
        if (ObjectUtils.isNotEmpty(tensionDeviVal)) {
            tensionDeviValRes = tensionDeviVal.divide(BigDecimal.valueOf(100), 3, BigDecimal.ROUND_HALF_UP);
        }
    }

    public List<TensionRecording> estimateData(List<TensionRecordingResVo> vos, List<TensionRecording> recUpdateList) {
        unqualifiedParams = new ArrayList<>();

        // 根据linkCode分组
        Map<String, List<TensionRecordingResVo>> linkMap =
            vos.stream().filter(s -> Objects.nonNull(s.getLinkCode())).collect(Collectors.groupingBy(TensionRecordingResVo::getLinkCode));
        BigDecimal finalTensionDeviValRes = tensionDeviValRes;
        linkMap.forEach((key, val) -> {
            status = null;
            msgStatus = null;
            String recId = ObjectUtils.isNotEmpty(val.get(0)) ? val.get(0).getId() : null;
            // 根据孔号分组获取map
            Map<String, List<TensionRecordingResVo>> listMap =
                val.stream().filter(s -> Objects.nonNull(s.getHoleNumber())).collect(Collectors.groupingBy(TensionRecordingResVo::getHoleNumber));
            // 遍历map 比较同一孔号的2个张拉力的实测值
            listMap.forEach((k, item) -> {
                tqdStatus = null;
                hslStatus = null;
                TensionRecordingResVo currVo = null;
                for (TensionRecordingResVo vo: item) {
                    currVo = vo;
                    // 实际砼强度与砼设计值比例 实际值 >= 设计值* 0.9 || 实际砼强度为空或者为0 则默认合格
                    if (ObjectUtils.isEmpty(vo.getConcreteStrength())
                        || (BigDecimal.ZERO.compareTo(vo.getConcreteStrength())==0)
                        || (vo.getConcreteStrength().compareTo(vo.getConcreteDesign().multiply(concreteRatio)) != -1) ) {
                        // 回缩量上下限
                        if ((shrinkageAmountMaxValRes!=0 || shrinkageAmountMinValRes!=0) && ObjectUtils.isNotEmpty(vo.getShrinkageAmount())
                            && (vo.getShrinkageAmount() >= shrinkageAmountMinValRes || vo.getShrinkageAmount() <= shrinkageAmountMaxValRes)) {
                            // 未对比两台张拉仪的张拉力数据前 状态暂设置为-1
                            vo.setStatus("-1");
                            hslStatus = "1";
                            tqdStatus = "1";
                            status = "1";
                        } else if (shrinkageAmountMaxValRes==0 && shrinkageAmountMinValRes==0){
                            // 未对比两台张拉仪的张拉力数据前 状态暂设置为-1
                            vo.setStatus("-1");
                            hslStatus = "1";
                            tqdStatus = "1";
                            status = "1";
                        } else {
                            // 不合格
                            vo.setStatus("0");
                            hslStatus = "0";
                            tqdStatus = "1";
                            status = "0";
                        }
                    } else {
                        // 不合格
                        vo.setStatus("0");
                        tqdStatus = "0";
                        status = "0";
                    }
                }
                if (ObjectUtils.isNotEmpty(currVo)) {
                    if ("0".equals(hslStatus)) {
                        currVo.setStatus("0");
                        // 保存不合格参数
                        unqualifiedParams.add("孔号:" + k + TEXT2 + "回缩量:" + currVo.getShrinkageAmount() + TEXT2
                            + "超出上下限范围" + "("
                            + new BigDecimal(shrinkageAmountMinValRes*100).setScale(1, BigDecimal.ROUND_HALF_UP) + "%"
                            + TEXT3 + new BigDecimal(shrinkageAmountMaxValRes*100).setScale(1, BigDecimal.ROUND_HALF_UP) + "%"
                            + ")" + TEXT2);
                    }
                    if ("0".equals(tqdStatus)) {
                        currVo.setStatus("0");
                        // 应达到的砼强度值
                        BigDecimal actualVal = currVo.getConcreteDesign().multiply(concreteRatio);
                        // 保存不合格参数
                        unqualifiedParams.add("孔号:" + k + TEXT2 + "实际砼强度:" + currVo.getConcreteStrength() + TEXT2
                            + "设计砼强度:" + currVo.getConcreteDesign() + TEXT2
                            + "未达到" + actualVal + TEXT2
                            + "超出允许偏差" + "±" + concreteRatio.multiply(new BigDecimal(100)).setScale(1, BigDecimal.ROUND_HALF_UP) + "%"  + TEXT2);
                    }
                }

//                // 定义
//                String sclv = "伸长量";
//                BigDecimal totalSum = new BigDecimal(0);
//                BigDecimal designSum = new BigDecimal(0);
//                // 获取同一孔号的2个伸长量值总和
//                for (TensionRecordingResVo res: item) {
//                    if (ObjectUtils.isNotEmpty(res.getMeasurementPoint()) && res.getMeasurementPoint().contains(sclv)) {
//                        totalSum = res.getTotalExtension().add(totalSum);
//                        designSum = res.getDesignExtension().add(designSum);
//                    }
//                }
//                // 伸长值校验 = (2个实际伸长值的和 - 2个设计伸长值的和) / (2个设计伸长值的和)
//                if (!(BigDecimal.ZERO.compareTo(designSum)==0) && ( (totalSum.subtract(designSum)).divide(designSum, 3, BigDecimal.ROUND_HALF_UP).abs().compareTo(extensionDeviRatioRes) != 1 )) {
//                    // 合格
//                    status = "1";
//                } else {
//                    // 不合格
//                    status = "0";
//                    if (ObjectUtils.isNotEmpty(currVo) && !(BigDecimal.ZERO.compareTo(designSum)==0)) {
//                        // 实际偏差
//                        BigDecimal actualError = (totalSum.subtract(designSum)).divide(designSum, 3, BigDecimal.ROUND_HALF_UP);
//                        // 保存不合格参数
//                        unqualifiedParams.add("孔号:" + k + TEXT2 + "实际伸长值:" + totalSum + TEXT2
//                            + "理论伸长值:" + designSum + TEXT2
//                            + "实际偏差" + (actualError.multiply(new BigDecimal(100)).setScale(1, BigDecimal.ROUND_HALF_UP).abs()) + "%" + TEXT2
//                            + "超出允许偏差" + "±" + extensionDeviRatioRes.multiply(new BigDecimal(100)).setScale(1, BigDecimal.ROUND_HALF_UP) + "%" + TEXT2);
//                    }
//                }

                // 定义
                String sclv = "伸长量";
                // 获取
                if (ObjectUtils.isNotEmpty(item.get(0)) && ObjectUtils.isNotEmpty(item.get(0).getMeasurementPoint()) && item.get(0).getMeasurementPoint().contains(sclv)) {
                    BigDecimal firstActual = new BigDecimal(0);
                    BigDecimal firstDesign = new BigDecimal(0);
                    firstActual = item.get(0).getTotalExtension();
                    firstDesign = item.get(0).getDesignExtension();
                    // 伸长值校验 = (第一个实际伸长值 - 第一个设计伸长值) / (第一个设计伸长值)
                    if (!(BigDecimal.ZERO.compareTo(firstDesign)==0) && ( (firstActual.subtract(firstDesign)).divide(firstDesign, 3, BigDecimal.ROUND_HALF_UP).abs().compareTo(extensionDeviRatioRes) != 1 )) {
                        // 合格
                        item.get(0).setStatus("1");
                        status = "1";
                    } else {
                        // 不合格
                        status = "0";
                        if (ObjectUtils.isNotEmpty(currVo) && !(BigDecimal.ZERO.compareTo(firstDesign)==0)) {
                            item.get(0).setStatus("0");
                            // 实际偏差
                            BigDecimal actualError = (firstActual.subtract(firstDesign)).divide(firstDesign, 3, BigDecimal.ROUND_HALF_UP);
                            // 保存不合格参数
                            unqualifiedParams.add("孔号:" + k + TEXT2 + "实际伸长值:" + firstActual + TEXT2
                                + "理论伸长值:" + firstDesign + TEXT2
                                + "实际偏差" + (actualError.multiply(new BigDecimal(100)).setScale(1, BigDecimal.ROUND_HALF_UP).abs()) + "%" + TEXT2
                                + "超出允许偏差" + "±" + extensionDeviRatioRes.multiply(new BigDecimal(100)).setScale(1, BigDecimal.ROUND_HALF_UP) + "%" + TEXT2);
                        }
                    }
                }

                List<TensionRecordingResVo> zlls = new ArrayList<>();
                String zllv = "张拉力";
                // 获取同一孔号的2个张拉力值
                for (TensionRecordingResVo res: item) {
                    if (ObjectUtils.isNotEmpty(res.getMeasurementPoint()) && res.getMeasurementPoint().contains(zllv)) {
                        zlls.add(res);
                    }
                }
                // 比较同一孔号的2个张拉力值(比较第一二三四测试值取最大值)
                if (CollectionUtils.isNotEmpty(zlls) && zlls.size() % 2 == 0 && ObjectUtils.isNotEmpty(zlls.get(0)) && ObjectUtils.isNotEmpty(zlls.get(1))) {
                    // 获取第一二三四测试值
                    BigDecimal firstStroke1 = ObjectUtils.isNotEmpty(zlls.get(0).getFirstStroke()) ? new BigDecimal(zlls.get(0).getFirstStroke()) : new BigDecimal(0);
                    BigDecimal secondStroke1 = ObjectUtils.isNotEmpty(zlls.get(0).getSecondStroke()) ? new BigDecimal(zlls.get(0).getSecondStroke()) : new BigDecimal(0);
                    BigDecimal thirdStroke1 = ObjectUtils.isNotEmpty(zlls.get(0).getThirdStroke()) ? new BigDecimal(zlls.get(0).getThirdStroke()) : new BigDecimal(0);
                    BigDecimal fourthStroke1 = ObjectUtils.isNotEmpty(zlls.get(0).getFourthStroke()) ? new BigDecimal(zlls.get(0).getFourthStroke()) : new BigDecimal(0);

                    BigDecimal firstStroke2 = ObjectUtils.isNotEmpty(zlls.get(1).getFirstStroke()) ? new BigDecimal(zlls.get(1).getFirstStroke()) : new BigDecimal(1);
                    BigDecimal secondStroke2 = ObjectUtils.isNotEmpty(zlls.get(1).getSecondStroke()) ? new BigDecimal(zlls.get(1).getSecondStroke()) : new BigDecimal(1);
                    BigDecimal thirdStroke2 = ObjectUtils.isNotEmpty(zlls.get(1).getThirdStroke()) ? new BigDecimal(zlls.get(1).getThirdStroke()) : new BigDecimal(1);
                    BigDecimal fourthStroke2 = ObjectUtils.isNotEmpty(zlls.get(1).getFourthStroke()) ? new BigDecimal(zlls.get(1).getFourthStroke()) : new BigDecimal(1);

                    String firstStroke3 = zlls.get(0).getFirstStroke();
                    String secondStroke3 = zlls.get(0).getSecondStroke();
                    String thirdStroke3 = zlls.get(0).getThirdStroke();
                    String fourthStroke3 = zlls.get(0).getFourthStroke();

                    String firstStroke4 = zlls.get(1).getFirstStroke();
                    String secondStroke4 = zlls.get(1).getSecondStroke();
                    String thirdStroke4 = zlls.get(1).getThirdStroke();
                    String fourthStroke4 = zlls.get(1).getFourthStroke();

                    // 第四行程没有 取第三行程 若无 取第二行程 若无 取第一行程
                    if (ObjectUtils.isNotEmpty(fourthStroke3) && ObjectUtils.isNotEmpty(fourthStroke4) && !(BigDecimal.ZERO.compareTo(fourthStroke1)==0) ) {
                        if ((fourthStroke1.subtract(fourthStroke2)).divide(fourthStroke1, 3, BigDecimal.ROUND_HALF_UP).compareTo(finalTensionDeviValRes) != 1) {
                            // 遍历集合 这组孔号状态设置为合格
                            for (TensionRecordingResVo res: item) {
                                res.setStatus("1");
                            }
                            if (!"1".equals(status)) {
                                status = "1";
                            }
                        } else {
                            // 遍历集合 这组桩号状态设置为不合格
                            for (TensionRecordingResVo res: item) {
                                res.setStatus("0");
                            }
                            status = "0";
                            // 实际偏差
                            BigDecimal actualError = (fourthStroke1.subtract(fourthStroke2)).divide(fourthStroke1, 3, BigDecimal.ROUND_HALF_UP);
                            // 保存不合格参数
                            unqualifiedParams.add("孔号:" + k + TEXT2 + "张拉力值:" + fourthStroke1+","+fourthStroke2 + TEXT2
                                + "实际偏差" + (actualError.multiply(new BigDecimal(100)).setScale(1, BigDecimal.ROUND_HALF_UP).abs()) + "%" + TEXT2
                                + "超出允许偏差" +  "±" + finalTensionDeviValRes.multiply(new BigDecimal(100)).setScale(1, BigDecimal.ROUND_HALF_UP) + "%" + TEXT2);
                        }
                    }
                    else if (ObjectUtils.isNotEmpty(thirdStroke3) && ObjectUtils.isNotEmpty(thirdStroke4) && !(BigDecimal.ZERO.compareTo(thirdStroke1)==0) ) {
                        if ((thirdStroke1.subtract(thirdStroke2)).divide(thirdStroke1, 3, BigDecimal.ROUND_HALF_UP).compareTo(finalTensionDeviValRes) != 1) {
                            // 遍历集合 这组孔号状态设置为合格
                            for (TensionRecordingResVo res: item) {
                                res.setStatus("1");
                            }
                            if (!"1".equals(status)) {
                                status = "1";
                            }
                        } else {
                            // 遍历集合 这组桩号状态设置为不合格
                            for (TensionRecordingResVo res: item) {
                                res.setStatus("0");
                            }
                            status = "0";
                            // 实际偏差
                            BigDecimal actualError = (thirdStroke1.subtract(thirdStroke2)).divide(thirdStroke1, 3, BigDecimal.ROUND_HALF_UP);
                            // 保存不合格参数
                            unqualifiedParams.add("孔号:" + k + TEXT2 + "张拉力值:" + thirdStroke1+","+thirdStroke2 + TEXT2
                                + "实际偏差" + (actualError.multiply(new BigDecimal(100)).setScale(1, BigDecimal.ROUND_HALF_UP).abs()) + "%" + TEXT2
                                + "超出允许偏差" + "±" + finalTensionDeviValRes.multiply(new BigDecimal(100)).setScale(1, BigDecimal.ROUND_HALF_UP) + "%" + TEXT2);
                        }
                    }
                    else if (ObjectUtils.isNotEmpty(secondStroke3) && ObjectUtils.isNotEmpty(secondStroke4) && !(BigDecimal.ZERO.compareTo(secondStroke1)==0) ) {
                        if ((secondStroke1.subtract(secondStroke2)).divide(secondStroke1, 3, BigDecimal.ROUND_HALF_UP).compareTo(finalTensionDeviValRes) != 1) {
                            // 遍历集合 这组孔号状态设置为合格
                            for (TensionRecordingResVo res: item) {
                                res.setStatus("1");
                            }
                            if (!"1".equals(status)) {
                                status = "1";
                            }
                        } else {
                            // 遍历集合 这组桩号状态设置为不合格
                            for (TensionRecordingResVo res: item) {
                                res.setStatus("0");
                            }
                            status = "0";
                            // 实际偏差
                            BigDecimal actualError = (secondStroke1.subtract(secondStroke2)).divide(secondStroke1, 3, BigDecimal.ROUND_HALF_UP);
                            // 保存不合格参数
                            unqualifiedParams.add("孔号:" + k + TEXT2 + "张拉力值:" + secondStroke1+","+secondStroke2 + TEXT2
                                + "实际偏差" + (actualError.multiply(new BigDecimal(100)).setScale(1, BigDecimal.ROUND_HALF_UP).abs()) + "%" + TEXT2
                                + "超出允许偏差" + "±" + finalTensionDeviValRes.multiply(new BigDecimal(100)).setScale(1, BigDecimal.ROUND_HALF_UP) + "%" + TEXT2);
                        }
                    }
                    else if (ObjectUtils.isNotEmpty(firstStroke3) && ObjectUtils.isNotEmpty(firstStroke4) && !(BigDecimal.ZERO.compareTo(firstStroke1)==0) ) {
                        if ((firstStroke1.subtract(firstStroke2)).divide(firstStroke1, 3, BigDecimal.ROUND_HALF_UP).compareTo(finalTensionDeviValRes) != 1) {
                            // 遍历集合 这组孔号状态设置为合格
                            for (TensionRecordingResVo res: item) {
                                res.setStatus("1");
                            }
                            if (!"1".equals(status)) {
                                status = "1";
                            }
                        } else {
                            // 遍历集合 这组桩号状态设置为不合格
                            for (TensionRecordingResVo res: item) {
                                res.setStatus("0");
                            }
                            status = "0";
                            // 实际偏差
                            BigDecimal actualError = (firstStroke1.subtract(firstStroke2)).divide(firstStroke1, 3, BigDecimal.ROUND_HALF_UP);
                            // 保存不合格参数
                            unqualifiedParams.add("孔号:" + k + TEXT2 + "张拉力值:" + firstStroke1+","+firstStroke2 + TEXT2
                                + "实际偏差" + (actualError.multiply(new BigDecimal(100)).setScale(1, BigDecimal.ROUND_HALF_UP).abs()) + "%" + TEXT2
                                + "超出允许偏差" + "±" + finalTensionDeviValRes.multiply(new BigDecimal(100)).setScale(1, BigDecimal.ROUND_HALF_UP) + "%" + TEXT2);
                        }
                    }
                    else {
                        // 遍历集合 这组桩号状态设置为不合格
                        for (TensionRecordingResVo res: item) {
                            res.setStatus("0");
                        }
                        status = "0";
                        msgStatus = "1";
                        // 保存不合格参数
                        unqualifiedParams.add("孔号:" + k + TEXT2 + "检测到张拉力值采集异常,无法判断是否合格,请联系系统管理员!");
//                        System.out.println("提示：检测到该条张拉数据的张拉力值采集异常，无法判断是否合格，请联系系统管理员！");
                    }
                }

            });
            // 更新状态
            if (ObjectUtils.isNotEmpty(unqualifiedParams) && unqualifiedParams.size() > 0) {
                status = "0";
            } else {
                status = "1";
            }
            if (ObjectUtils.isNotEmpty(recId) && ObjectUtils.isNotEmpty(status)) {
                // 创建更新对象
                TensionRecording tensionRecording = new TensionRecording();
                tensionRecording.setId(recId);
                tensionRecording.setStatus(status);
                recUpdateList.add(tensionRecording);
            }
        });
        return recUpdateList;
    }

    /**
     * 短信推送及预警信息保存
     * @param deptId
     * @param tensionRecordingVo
     */
    private void sendMsg(String deptId, TensionRecordingResVo tensionRecordingVo, int isSend) {
        String message = null;
        int send = 1;
        // 是否发送消息 1发送 0不发
        if (isSend == 1) {
            if (!"1".equals(status)) {
                // 发送内容: 标段 设备名称 张拉梁型 梁号
                // 短信推送样例：【山东高速】xx标段，xx拌合站的xx施工部位采用的xx配方的外加剂1产生了初级预警,超出标准值或低于标准值xx%。
                String deptName = ObjectUtils.isNotEmpty(tensionRecordingVo.getDeptName()) ? "【" + tensionRecordingVo.getDeptName() : "【";
                String deviceName = ObjectUtils.isNotEmpty(tensionRecordingVo.getDeviceName()) ? tensionRecordingVo.getDeviceName() : "";
                String instrumentManufacturer = ObjectUtils.isNotEmpty(tensionRecordingVo.getInstrumentManufacturer()) ? tensionRecordingVo.getInstrumentManufacturer() : "";
                String stake = "桩号:" + (ObjectUtils.isNotEmpty(tensionRecordingVo.getStake()) ? tensionRecordingVo.getStake() : "");
                String beamNo = "梁号:" + (ObjectUtils.isNotEmpty(tensionRecordingVo.getBeamNo()) ? tensionRecordingVo.getBeamNo() : "");
                String beamType = "梁型:" + (ObjectUtils.isNotEmpty(tensionRecordingVo.getBeamType()) ? tensionRecordingVo.getBeamType() : "");
//                String start = "【山东高速】";
                String start = "";
                String separator = " ";
                String common = "】的张拉数据产生了预警信息: ";
                // 不合格参数
                String params = "";
                for (Object str : unqualifiedParams) {
                    params += str;
                }
                params += "不合格;";
                if (ObjectUtils.isEmpty(msgStatus)) { // 不合格信息
                    message =  start + deptName + separator + deviceName + separator + instrumentManufacturer + separator  + stake + separator + beamNo + separator + beamType + common + params;
                }
                // 不合格参数
                String params2 = "";
                for (Object str : unqualifiedParams) { // 异常信息
                    params2 += str;
                }
                if ("1".equals(msgStatus)) {
                    message =  start + deptName + separator + deviceName + separator + instrumentManufacturer + separator  + stake + separator + beamNo + separator + beamType + common + params2;
                }
            }
            // 根据deptId获取祖级列表
            SysDept dept = sysDeptMapper.getById(Long.valueOf(deptId));
            String ancestors = ObjectUtils.isNotEmpty(dept) ? dept.getAncestors() : null;
            String[] ids = ObjectUtils.isNotEmpty(ancestors) ? ancestors.split(",") : new String[]{} ;
            // 根据部门id获取预警标识
            ZjNWarningUsing entity = zjNWarningUsingMapper.getByDeptId(deptId, ids);
            Long msgZlyj = ObjectUtils.isNotEmpty(entity) ? entity.getUsingMsgZlyj() : 0;
            if (msgZlyj == 1 && !"1".equals(status)) {
                // 发送人获取:
                ZjNWarningUserMessageBo bo = new ZjNWarningUserMessageBo();
                bo.setId(deptId);
                QueryWrapper<ZjNWarningUserMessage> wrapper1 = new QueryWrapper<>();
                wrapper1.eq("a.del_flag", "0");
                wrapper1.eq("u.del_flag", "0");
                wrapper1.like("a.warn_val_zlyj", "%1%");
                List<ZjNWarningUserMessageVo> list = zjNWarningUserMessageMapper.getZlyjList(wrapper1, bo);
                List<String> phonenumber = list.stream().map(ZjNWarningUserMessageVo::getPhonenumber).collect(Collectors.toList());
                // 预警发送及保存
                try {
                    send = iZjNWarningUsingService.send(phonenumber, message);
                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.println("短信发送失败");
                }
            }
        }
        // 不合格则产生预警信息
        if (!"1".equals(status)) {
            // 推送失败 返1 成功 返0
            ZjNWarningZlyj zjNWarningZlyj = new ZjNWarningZlyj();
            zjNWarningZlyj.setType("1");
            zjNWarningZlyj.setInsterTime(new Date());
            zjNWarningZlyj.setRemark(message);
            zjNWarningZlyj.setBusinessId(tensionRecordingVo.getId());
            zjNWarningZlyj.setStatus("0");
            zjNWarningZlyj.setDisposalStatus(1); // 未处置状态
            zjNWarningZlyjMapper.insert(zjNWarningZlyj);
        }
    }
}
